package cn.lg.soar.common.algorithm;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECPoint;

import java.security.SecureRandom;

import static cn.lg.soar.common.util.data.DataUtil.BASE64EN;

/**
 * SM2编码器
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class SM2Encoder {

    private final SM2Engine sm2Engine;
    protected final static X9ECParameters SM2EC_PARAMETERS = GMNamedCurves.getByName("sm2p256v1");
    protected final static ECDomainParameters EC_DOMAIN_PARAMETERS = new ECDomainParameters(SM2EC_PARAMETERS.getCurve(), SM2EC_PARAMETERS.getG(), SM2EC_PARAMETERS.getN());

    public SM2Encoder(byte[] publicKey, SM2Engine.Mode mode) {
        //提取公钥点
        ECPoint ecPoint = SM2EC_PARAMETERS.getCurve().decodePoint(publicKey);
        // 公钥前面的02或者03表示是压缩公钥，04表示未压缩公钥, 04的时候，可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(ecPoint, EC_DOMAIN_PARAMETERS);
        sm2Engine = new SM2Engine(mode);
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
    }

    public SM2Encoder(byte[] publicKey) {
        this(publicKey, SM2Engine.Mode.C1C3C2);
    }

    /**
     * 加密
     * @param data 数据
     * @return
     */
    public byte[] encrypt(byte[] data) {
        try {
            return sm2Engine.processBlock(data, 0, data.length);
        } catch (InvalidCipherTextException e) {
            throw new AlgorithmException(e);
        }
    }

    /**
     * 加密
     * @param data 数据
     * @return
     */
    public String encryptToBase64(byte[] data) {
        return BASE64EN.encodeToString(
                this.encrypt(data)
        );
    }

}
